#ifndef _SOCKET_H_
#define _SOCKET_H_

#include <memory>

namespace Net
{

class TCPSocket
{
	int socket_;
	unsigned long int addr_;
	short port_;

	// Avoid overloading based on integral types
	class AssignOnlyTag{}; 
	TCPSocket(int socket, int addr, short port, AssignOnlyTag);
public:

	class Exception
	{
		const char *what_;
	public:
		Exception(const char *what) : what_(what) {};
		const char *what() const { return what_; }
	};

	TCPSocket(short port);
	TCPSocket();
	~TCPSocket();
	
	TCPSocket &operator =(const TCPSocket &rhs);
	void listen(int n = 5);

	void connect(const char *host, short port);

	const unsigned long int address() const { return addr_; }
	const char *addressString() const;
	const int port() const { return port_; }
	const int getImpl() const { return socket_; }

	void send(const void *data, size_t size);
	template <class T>
	void send(const T &data) {return send(&data, sizeof(data)); }

	void recv(void *data, size_t size);
	template <class T>
	void recv(T &data) {return recv(&data, sizeof(data)); }
	
	bool isReadable(int timeout);
	bool isError(int timeout);
	TCPSocket *accept();
};

}

#endif
